home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / compress.zip / COMPRESS.C < prev    next >
Text File  |  1994-07-10  |  37KB  |  1,445 lines

  1. /*
  2.  * Copyright (c) 1985, 1986 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * James A. Woods, derived from original work by Spencer Thomas
  7.  * and Joseph Orost.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  *    This product includes software developed by the University of
  20.  *    California, Berkeley and its contributors.
  21.  * 4. Neither the name of the University nor the names of its contributors
  22.  *    may be used to endorse or promote products derived from this software
  23.  *    without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35.  * SUCH DAMAGE.
  36.  */
  37.  
  38. #ifndef lint
  39. char copyright[] =
  40. "@(#) Copyright (c) 1985, 1986 The Regents of the University of California.\n\
  41.  All rights reserved.\n";
  42. #endif /* not lint */
  43.  
  44. #ifndef lint
  45. static char sccsid[] = "@(#)compress.c    5.19 (Berkeley) 3/18/91";
  46. #endif /* not lint */
  47.  
  48. #define    MAXPATHLEN    160
  49. #define    BUFSIZ        2048
  50. char    tmp[256];
  51.  
  52. /*
  53.  * compress.c - File compression ala IEEE Computer, June 1984.
  54.  *
  55.  * Authors:    Spencer W. Thomas    (decvax!utah-cs!thomas)
  56.  *        Jim McKie        (decvax!mcvax!jim)
  57.  *        Steve Davies        (decvax!vax135!petsd!peora!srd)
  58.  *        Ken Turkowski        (decvax!decwrl!turtlevax!ken)
  59.  *        James A. Woods        (decvax!ihnp4!ames!jaw)
  60.  *        Joe Orost        (decvax!vax135!petsd!joe)
  61.  */
  62.  
  63.  
  64. #include <sys/stat.h>
  65. #include <signal.h>
  66. typedef _CatcherPTR sig_t;
  67. #include <utime.h>
  68. #include <errno.h>
  69. #include <stdio.h>
  70. #include <ctype.h>
  71. #include <stdlib.h>
  72. #include <string.h>
  73. #include <dos.h>
  74. #include <io.h>
  75. #include <windows.h>
  76. #define index strchr
  77. #define rindex strrchr
  78. #define    MIN(a,b) ((a) < (b) ? (a) : (b))
  79. void usage(void);
  80. void compress(void);
  81. void decompress(void);
  82. void writeerr(void);
  83. void prratio(FILE *, long, long);
  84. void copystat(char *, char *);
  85. void cl_block(void);
  86.  
  87. /*
  88.  * Set USERMEM to the maximum amount of physical user memory available
  89.  * in bytes.  USERMEM is used to determine the maximum BITS that can be used
  90.  * for compression.
  91.  *
  92.  * SACREDMEM is the amount of physical memory saved for others; compress
  93.  * will hog the rest.
  94.  */
  95. #ifndef SACREDMEM
  96. #define SACREDMEM    0
  97. #endif
  98.  
  99. #ifndef USERMEM
  100. # define USERMEM     450000    /* default user memory */
  101. #endif
  102. int    opterr = 1,        /* if error message should be printed */
  103.     optind = 1,        /* index into parent argv vector */
  104.     optopt;            /* character checked for validity */
  105. char    *optarg;        /* argument associated with option */
  106.  
  107. #define    BADCH    (int)'?'
  108. #define    EMSG    ""
  109.  
  110. int
  111. getopt(int nargc, char * const *nargv, char const *ostr)
  112. {
  113.     static char *place = EMSG;        /* option letter processing */
  114.     register char *oli;            /* option letter list index */
  115.     char *p;
  116.  
  117.     if (!*place) {                /* update scanning pointer */
  118.         if (optind >= nargc || *(place = nargv[optind]) != '-') {
  119.             place = EMSG;
  120.             return(EOF);
  121.         }
  122.         if (place[1] && *++place == '-') {    /* found "--" */
  123.             ++optind;
  124.             place = EMSG;
  125.             return(EOF);
  126.         }
  127.     }                    /* option letter okay? */
  128.     if ((optopt = (int)*place++) == (int)':' ||
  129.         (oli = index(ostr, optopt)) == 0) {
  130.         /*
  131.          * if the user didn't specify '-' as an option,
  132.          * assume it means EOF.
  133.          */
  134.         if (optopt == (int)'-')
  135.             return(EOF);
  136.         if (!*place)
  137.             ++optind;
  138.         if (opterr) {
  139.             if ((p = rindex(*nargv, '/')) == 0)
  140.                 p = *nargv;
  141.             else
  142.                 ++p;
  143.             (void)fprintf(stderr, "%s: illegal option -- %c\n",
  144.                 p, optopt);
  145.         }
  146.         return(BADCH);
  147.     }
  148.     if (*++oli != ':') {            /* don't need argument */
  149.         optarg = NULL;
  150.         if (!*place)
  151.             ++optind;
  152.     }
  153.     else {                    /* need an argument */
  154.         if (*place)            /* no white space */
  155.             optarg = place;
  156.         else if (nargc <= ++optind) {    /* no arg */
  157.             place = EMSG;
  158.             if ((p = rindex(*nargv, '/')) == 0)
  159.                 p = *nargv;
  160.             else
  161.                 ++p;
  162.             if (opterr)
  163.                 (void)fprintf(stderr,
  164.                     "%s: option requires an argument -- %c\n",
  165.                     p, optopt);
  166.             return(BADCH);
  167.         }
  168.          else                /* white space */
  169.             optarg = nargv[optind];
  170.         place = EMSG;
  171.         ++optind;
  172.     }
  173.     return(optopt);                /* dump back option letter */
  174. }
  175.  
  176. #ifdef pdp11
  177. # define BITS     12    /* max bits/code for 16-bit machine */
  178. # define NO_UCHAR    /* also if "unsigned char" functions as signed char */
  179. # undef USERMEM 
  180. #endif /* pdp11 */    /* don't forget to compile with -i */
  181.  
  182. #ifdef USERMEM
  183. # if USERMEM >= (433484+SACREDMEM)
  184. #  define PBITS    16
  185. # else
  186. #  if USERMEM >= (229600+SACREDMEM)
  187. #   define PBITS    15
  188. #  else
  189. #   if USERMEM >= (127536+SACREDMEM)
  190. #    define PBITS    14
  191. #   else
  192. #    if USERMEM >= (73464+SACREDMEM)
  193. #     define PBITS    13
  194. #    else
  195. #     define PBITS    12
  196. #    endif
  197. #   endif
  198. #  endif
  199. # endif
  200. # undef USERMEM
  201. #endif /* USERMEM */
  202.  
  203. #ifdef PBITS        /* Preferred BITS for this memory size */
  204. # ifndef BITS
  205. #  define BITS PBITS
  206. # endif BITS
  207. #endif /* PBITS */
  208.  
  209. #if BITS == 16
  210. # define HSIZE    69001        /* 95% occupancy */
  211. #endif
  212. #if BITS == 15
  213. # define HSIZE    35023        /* 94% occupancy */
  214. #endif
  215. #if BITS == 14
  216. # define HSIZE    18013        /* 91% occupancy */
  217. #endif
  218. #if BITS == 13
  219. # define HSIZE    9001        /* 91% occupancy */
  220. #endif
  221. #if BITS <= 12
  222. # define HSIZE    5003        /* 80% occupancy */
  223. #endif
  224.  
  225. /*
  226.  * a code_int must be able to hold 2**BITS values of type int, and also -1
  227.  */
  228. #if BITS > 15
  229. typedef long int    code_int;
  230. #else
  231. typedef int        code_int;
  232. #endif
  233.  
  234. #ifdef SIGNED_COMPARE_SLOW
  235. typedef unsigned long int count_int;
  236. typedef unsigned short int count_short;
  237. #else
  238. typedef long int      count_int;
  239. #endif
  240.  
  241. void    cl_hash(count_int);
  242. void    output(code_int);
  243.  
  244. #ifdef NO_UCHAR
  245.  typedef char    char_type;
  246. #else
  247.  typedef    unsigned char    char_type;
  248. #endif /* UCHAR */
  249. char_type magic_header[] = { "\037\235" };    /* 1F 9D */
  250.  
  251. /* Defines for third byte of header */
  252. #define BIT_MASK    0x1f
  253. #define BLOCK_MASK    0x80
  254. /* Masks 0x40 and 0x20 are free.  I think 0x20 should mean that there is
  255.    a fourth header byte (for expansion).
  256. */
  257. #define INIT_BITS 9            /* initial number of bits/code */
  258.  
  259. int n_bits;                /* number of bits/code */
  260. int maxbits = BITS;            /* user settable max # bits/code */
  261. code_int maxcode;            /* maximum code, given n_bits */
  262. code_int maxmaxcode = 1l << BITS;    /* should NEVER generate this code */
  263. #ifdef COMPATIBLE        /* But wrong! */
  264. # define MAXCODE(n_bits)    (1l << (n_bits) - 1)
  265. #else
  266. # define MAXCODE(n_bits)    ((1l << (n_bits)) - 1)
  267. #endif /* COMPATIBLE */
  268.  
  269. count_int huge *htab;
  270. unsigned short huge *codetab;
  271. HGLOBAL    hmemHtab;
  272. HGLOBAL    hmemCodeTab;
  273.  
  274. #define htabof(i)    htab[i]
  275. #define codetabof(i)    codetab[i]
  276. code_int hsize = HSIZE;            /* for dynamic table sizing */
  277. count_int fsize;
  278.  
  279. /*
  280.  * To save much memory, we overlay the table used by compress() with those
  281.  * used by decompress().  The tab_prefix table is the same size and type
  282.  * as the codetab.  The tab_suffix table needs 2**BITS characters.  We
  283.  * get this from the beginning of htab.  The output stack uses the rest
  284.  * of htab, and contains characters.  There is plenty of room for any
  285.  * possible stack (stack used to be 8000 characters).
  286.  */
  287.  
  288. #define tab_prefixof(i)    codetabof(i)
  289. # define tab_suffixof(i)    ((char_type huge *)(htab))[i]
  290. # define de_stack        ((char_type huge *)&tab_suffixof(1L<<BITS))
  291.  
  292. code_int free_ent = 0;            /* first unused entry */
  293. int exit_stat = 0;            /* per-file status */
  294. int perm_stat = 0;            /* permanent status */
  295.  
  296. code_int getcode(void);
  297.  
  298. int nomagic = 0;    /* Use a 3-byte magic number header, unless old file */
  299. int zcat_flg = 0;    /* Write output on stdout, suppress messages */
  300. int precious = 1;    /* Don't unlink output file on interrupt */
  301. int quiet = 1;        /* don't tell me about compression */
  302.  
  303. /*
  304.  * block compression parameters -- after all codes are used up,
  305.  * and compression rate changes, start over.
  306.  */
  307. int block_compress = BLOCK_MASK;
  308. int clear_flg = 0;
  309. long int ratio = 0;
  310. #define CHECK_GAP 10000    /* ratio check interval */
  311. count_int checkpoint = CHECK_GAP;
  312. /*
  313.  * the next two codes should not be changed lightly, as they must not
  314.  * lie within the contiguous general code space.
  315.  */ 
  316. #define FIRST    257    /* first free entry */
  317. #define    CLEAR    256    /* table clear output code */
  318.  
  319. int force = 0;
  320. char ofname [100];
  321. #ifdef DEBUG
  322. int debug, verbose;
  323. #endif
  324. sig_t oldint;
  325. int bgnd_flag;
  326.  
  327. int do_decomp = 0;
  328.  
  329. /*-
  330.  * Algorithm from "A Technique for High Performance Data Compression",
  331.  * Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19.
  332.  *
  333.  * Usage: compress [-dfvc] [-b bits] [file ...]
  334.  * Inputs:
  335.  *    -d:        If given, decompression is done instead.
  336.  *
  337.  *      -c:         Write output on stdout, don't remove original.
  338.  *
  339.  *      -b:         Parameter limits the max number of bits/code.
  340.  *
  341.  *    -f:        Forces output file to be generated, even if one already
  342.  *            exists, and even if no space is saved by compressing.
  343.  *            If -f is not used, the user will be prompted if stdin is
  344.  *            a tty, otherwise, the output file will not be overwritten.
  345.  *
  346.  *      -v:        Write compression statistics
  347.  *
  348.  *     file ...:   Files to be compressed.  If none specified, stdin
  349.  *            is used.
  350.  * Outputs:
  351.  *    file.Z:        Compressed form of file with same mode, owner, and utimes
  352.  *     or stdout   (if stdin used as input)
  353.  *
  354.  * Assumptions:
  355.  *    When filenames are given, replaces with the compressed version
  356.  *    (.Z suffix) only if the file decreases in size.
  357.  * Algorithm:
  358.  *     Modified Lempel-Ziv method (LZW).  Basically finds common
  359.  * substrings and replaces them with a variable size code.  This is
  360.  * deterministic, and can be done on the fly.  Thus, the decompression
  361.  * procedure needs no input table, but tracks the way the table was built.
  362.  */
  363.  
  364. main(argc, argv)
  365.     int argc;
  366.     char **argv;
  367. {
  368.     extern int optind;
  369.     extern char *optarg;
  370.     struct stat statbuf;
  371.     int ch, overwrite;
  372.     char **filelist, **fileptr, *cp, tempname[MAXPATHLEN];
  373.     void onintr(), oops();
  374.  
  375.     hmemHtab = GlobalAlloc(GMEM_FIXED, (long) sizeof(count_int) * HSIZE);
  376.     if (!hmemHtab)
  377.     {
  378.         fprintf(stderr, "Out of memory\n");
  379.         exit(1);
  380.     }
  381.     hmemCodeTab = GlobalAlloc(GMEM_FIXED, (long) sizeof(unsigned short) * HSIZE);
  382.     if (!hmemCodeTab)
  383.     {
  384.         GlobalFree(hmemHtab);
  385.         fprintf(stderr, "Out of memory");
  386.     }
  387.     htab = (count_int huge *) GlobalLock(hmemHtab);
  388.     codetab = (unsigned short huge *) GlobalLock(hmemCodeTab);
  389.  
  390.     /* This bg check only works for sh. */
  391.     if ((oldint = signal(SIGINT, SIG_IGN)) != SIG_IGN) {
  392.         (void)signal(SIGINT, onintr);
  393.         (void)signal(SIGSEGV, oops);        /* XXX */
  394.     }
  395.     bgnd_flag = oldint != SIG_DFL;
  396.     
  397. #ifdef COMPATIBLE
  398.     nomagic = 1;        /* Original didn't have a magic number */
  399. #endif
  400.  
  401.     if ((cp = rindex(argv[0], '/')) != 0)
  402.         ++cp;
  403.     else
  404.         cp = argv[0];
  405.     if (strcmp(cp, "uncompress") == 0)
  406.         do_decomp = 1;
  407.     else if(strcmp(cp, "zcat") == 0) {
  408.         do_decomp = 1;
  409.         zcat_flg = 1;
  410.     }
  411.  
  412.     /*
  413.      * -b maxbits => maxbits.
  414.      * -C => generate output compatible with compress 2.0.
  415.      * -c => cat all output to stdout
  416.      * -D => debug
  417.      * -d => do_decomp
  418.      * -f => force overwrite of output file
  419.      * -n => no header: useful to uncompress old files
  420.      * -V => print Version; debug verbose
  421.      * -v => unquiet
  422.      */
  423.     
  424.     overwrite = 0;
  425. #ifdef DEBUG
  426.     while ((ch = getopt(argc, argv, "b:CcDdfnVv")) != EOF)
  427. #else
  428.     while ((ch = getopt(argc, argv, "b:Ccdfnv")) != EOF)
  429. #endif
  430.         switch(ch) {
  431.         case 'b':
  432.             maxbits = atoi(optarg);
  433.             break;
  434.         case 'C':
  435.             block_compress = 0;
  436.             break;
  437.         case 'c':
  438.             zcat_flg = 1;
  439.             break;
  440. #ifdef DEBUG
  441.         case 'D':
  442.             debug = 1;
  443.             break;
  444. #endif
  445.         case 'd':
  446.             do_decomp = 1;
  447.             break;
  448.         case 'f':
  449.             overwrite = 1;
  450.             force = 1;
  451.             break;
  452.         case 'n':
  453.             nomagic = 1;
  454.             break;
  455.         case 'q':
  456.             quiet = 1;
  457.             break;
  458. #ifdef DEBUG
  459.         case 'V':
  460.             verbose = 1;
  461.             break;
  462. #endif
  463.         case 'v':
  464.             quiet = 0;
  465.             break;
  466.         case '?':
  467.         default:
  468.             usage();
  469.         }
  470.     argc -= optind;
  471.     argv += optind;
  472.  
  473.     if (maxbits < INIT_BITS)
  474.         maxbits = INIT_BITS;
  475.     if (maxbits > BITS)
  476.         maxbits = BITS;
  477.     maxmaxcode = 1l << maxbits;
  478.  
  479.     /* Build useless input file list. */
  480.     filelist = fileptr = (char **)(malloc((argc + 1) * sizeof(*argv)));
  481.     while (*argv)
  482.         *fileptr++ = *argv++;
  483.     *fileptr = NULL;
  484.  
  485.     if (*filelist != NULL) {
  486.     for (fileptr = filelist; *fileptr; fileptr++) {
  487.         exit_stat = 0;
  488.         if (do_decomp) {            /* DECOMPRESSION */
  489.         /* Check for .Z suffix */
  490.         if (stricmp(*fileptr + strlen(*fileptr) - 2, ".Z") != 0) {
  491.             /* No .Z: tack one on */
  492.             strcpy(tempname, *fileptr);
  493.             strcat(tempname, ".Z");
  494.             *fileptr = tempname;
  495.         }
  496.         /* Open input file */
  497.         if ((freopen(*fileptr, "rb", stdin)) == NULL) {
  498.             fprintf(stderr, "%s: open: %s\n", *fileptr, sys_errlist[errno]);
  499.             gets(tmp);
  500.             perm_stat = 1;
  501.             continue;
  502.         }
  503.         /* Check the magic number */
  504.         if (nomagic == 0) {
  505.             if ((getchar() != (magic_header[0] & 0xFF))
  506.              || (getchar() != (magic_header[1] & 0xFF))) {
  507.             fprintf(stderr, "%s: not in compressed format\n",
  508.                 *fileptr);
  509.             continue;
  510.             }
  511.             maxbits = getchar();    /* set -b from file */
  512.             block_compress = maxbits & BLOCK_MASK;
  513.             maxbits &= BIT_MASK;
  514.             maxmaxcode = 1l << maxbits;
  515.             if(maxbits > BITS) {
  516.             fprintf(stderr,
  517.             "%s: compressed with %d bits, can only handle %d bits\n",
  518.             *fileptr, maxbits, BITS);
  519.             continue;
  520.             }
  521.         }
  522.         /* Generate output filename */
  523.         strcpy(ofname, *fileptr);
  524.         ofname[strlen(*fileptr) - 2] = '\0';  /* Strip off .Z */
  525.         } else {                    /* COMPRESSION */
  526.         if (stricmp(*fileptr + strlen(*fileptr) - 2, ".Z") == 0) {
  527.                 fprintf(stderr, "%s: already has .Z suffix -- no change\n",
  528.                 *fileptr);
  529.             continue;
  530.         }
  531.         /* Open input file */
  532.         if ((freopen(*fileptr, "rb", stdin)) == NULL) {
  533.             fprintf(stderr, "%s: open: %s\n", *fileptr, sys_errlist[errno]);
  534.             gets(tmp);
  535.             perm_stat = 1;
  536.             continue;
  537.         }
  538.         stat ( *fileptr, &statbuf );
  539.         fsize = (long) statbuf.st_size;
  540.         /*
  541.          * tune hash table size for small files -- ad hoc,
  542.          * but the sizes match earlier #defines, which
  543.          * serve as upper bounds on the number of output codes. 
  544.          */
  545.         hsize = HSIZE;
  546.         if ( fsize < (1 << 12) )
  547.             hsize = MIN ( 5003, HSIZE );
  548.         else if ( fsize < (1 << 13) )
  549.             hsize = MIN ( 9001, HSIZE );
  550.         else if ( fsize < (1 << 14) )
  551.             hsize = MIN ( 18013, HSIZE );
  552.         else if ( fsize < (1 << 15) )
  553.             hsize = MIN ( 35023, HSIZE );
  554.         else if ( fsize < 47000 )
  555.             hsize = MIN ( 50021, HSIZE );
  556.  
  557.         /* Generate output filename */
  558.         strcpy(ofname, *fileptr);
  559.         strcat(ofname, ".Z");
  560.         }
  561.         /* Check for overwrite of existing file */
  562.         if (overwrite == 0 && zcat_flg == 0) {
  563.         if (stat(ofname, &statbuf) == 0) {
  564.             char response[2];
  565.             response[0] = 'n';
  566.             fprintf(stderr, "%s already exists;", ofname);
  567.             if (bgnd_flag == 0 && isatty(2)) {
  568.             fprintf(stderr, " do you wish to overwrite %s (y or n)? ",
  569.             ofname);
  570.             fflush(stderr);
  571.             read(2, response, 2);
  572.             while (response[1] != '\n') {
  573.                 if (read(2, response+1, 1) < 0) {    /* Ack! */
  574.                 perror("stderr"); break;
  575.                 }
  576.             }
  577.             }
  578.             if (response[0] != 'y') {
  579.             fprintf(stderr, "\tnot overwritten\n");
  580.             continue;
  581.             }
  582.         }
  583.         }
  584.         if(zcat_flg == 0) {        /* Open output file */
  585.         if (freopen(ofname, "wb", stdout) == NULL) {
  586.             fprintf(stderr, "%s: create: %s\n", ofname, sys_errlist[errno]);
  587.             gets(tmp);
  588.             perm_stat = 1;
  589.             continue;
  590.         }
  591.         precious = 0;
  592.         if(!quiet)
  593.             fprintf(stderr, "%s: ", *fileptr);
  594.         }
  595.  
  596.         /* Actually do the compression/decompression */
  597.         if (do_decomp == 0)    compress();
  598. #ifndef DEBUG
  599.         else            decompress();
  600. #else
  601.         else if (debug == 0)    decompress();
  602.         else            printcodes();
  603.         if (verbose)        dump_tab();
  604. #endif /* DEBUG */
  605.         if(zcat_flg == 0) {
  606.         copystat(*fileptr, ofname);    /* Copy stats */
  607.         precious = 1;
  608.         if((exit_stat == 1) || (!quiet))
  609.             putc('\n', stderr);
  610.         }
  611.     }
  612.     } else {        /* Standard input */
  613.     if (do_decomp == 0) {
  614.         compress();
  615. #ifdef DEBUG
  616.         if(verbose)        dump_tab();
  617. #endif /* DEBUG */
  618.         if(!quiet)
  619.             putc('\n', stderr);
  620.     } else {
  621.         /* Check the magic number */
  622.         if (nomagic == 0) {
  623.         if ((getchar()!=(magic_header[0] & 0xFF))
  624.          || (getchar()!=(magic_header[1] & 0xFF))) {
  625.             GlobalUnlock(hmemHtab);
  626.             GlobalUnlock(hmemCodeTab);
  627.             GlobalFree(hmemHtab);
  628.             GlobalFree(hmemCodeTab);
  629.             fprintf(stderr, "stdin: not in compressed format\n");
  630.             exit(1);
  631.         }
  632.         maxbits = getchar();    /* set -b from file */
  633.         block_compress = maxbits & BLOCK_MASK;
  634.         maxbits &= BIT_MASK;
  635.         maxmaxcode = 1l << maxbits;
  636.         fsize = 100000;        /* assume stdin large for USERMEM */
  637.         if(maxbits > BITS) {
  638.             fprintf(stderr,
  639.             "stdin: compressed with %d bits, can only handle %d bits\n",
  640.             maxbits, BITS);
  641.             GlobalUnlock(hmemHtab);
  642.             GlobalUnlock(hmemCodeTab);
  643.             GlobalFree(hmemHtab);
  644.             GlobalFree(hmemCodeTab);
  645.             exit(1);
  646.         }
  647.         }
  648. #ifndef DEBUG
  649.         decompress();
  650. #else
  651.         if (debug == 0)    decompress();
  652.         else        printcodes();
  653.         if (verbose)    dump_tab();
  654. #endif /* DEBUG */
  655.     }
  656.     }
  657.     GlobalUnlock(hmemHtab);
  658.     GlobalUnlock(hmemCodeTab);
  659.     GlobalFree(hmemHtab);
  660.     GlobalFree(hmemCodeTab);
  661.     exit(perm_stat ? perm_stat : exit_stat);
  662.     return 1;
  663. }
  664.  
  665. static int offset;
  666. long int in_count = 1;            /* length of input */
  667. long int bytes_out;            /* length of compressed output */
  668. long int out_count = 0;            /* # of codes output (for debugging) */
  669.  
  670. /*
  671.  * compress stdin to stdout
  672.  *
  673.  * Algorithm:  use open addressing double hashing (no chaining) on the 
  674.  * prefix code / next character combination.  We do a variant of Knuth's
  675.  * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
  676.  * secondary probe.  Here, the modular division first probe is gives way
  677.  * to a faster exclusive-or manipulation.  Also do block compression with
  678.  * an adaptive reset, whereby the code table is cleared when the compression
  679.  * ratio decreases, but after the table fills.  The variable-length output
  680.  * codes are re-sized at this point, and a special CLEAR code is generated
  681.  * for the decompressor.  Late addition:  construct the table according to
  682.  * file size for noticeable speed improvement on small files.  Please direct
  683.  * questions about this implementation to ames!jaw.
  684.  */
  685.  
  686. void compress(void)
  687. {
  688.     register long fcode;
  689.     register code_int i = 0;
  690.     register int c;
  691.     register code_int ent;
  692.     register code_int disp;
  693.     register code_int hsize_reg;
  694.     register int hshift;
  695.  
  696. #ifndef COMPATIBLE
  697.     if (nomagic == 0) {
  698.     putchar(magic_header[0]);
  699.     putchar(magic_header[1]);
  700.     putchar((char)(maxbits | block_compress));
  701.     if(ferror(stdout))
  702.         writeerr();
  703.     }
  704. #endif /* COMPATIBLE */
  705.  
  706.     offset = 0;
  707.     bytes_out = 3;        /* includes 3-byte header mojo */
  708.     out_count = 0;
  709.     clear_flg = 0;
  710.     ratio = 0;
  711.     in_count = 1;
  712.     checkpoint = CHECK_GAP;
  713.     maxcode = MAXCODE(n_bits = INIT_BITS);
  714.     free_ent = ((block_compress) ? FIRST : 256 );
  715.  
  716.     ent = getchar ();
  717.  
  718.     hshift = 0;
  719.     for ( fcode = (long) hsize;  fcode < 65536L; fcode *= 2L )
  720.         hshift++;
  721.     hshift = 8 - hshift;        /* set hash code range bound */
  722.  
  723.     hsize_reg = hsize;
  724.     cl_hash( (count_int) hsize_reg);        /* clear hash table */
  725.  
  726. #ifdef SIGNED_COMPARE_SLOW
  727.     while ( (c = getchar()) != (unsigned) EOF ) {
  728. #else
  729.     while ( (c = getchar()) != EOF ) {
  730. #endif
  731.     in_count++;
  732.     fcode = (long) (((long) c << maxbits) + ent);
  733.      i = (((long) c << hshift) ^ ent);    /* xor hashing */
  734.  
  735.     if ( htabof (i) == fcode ) {
  736.         ent = codetabof (i);
  737.         continue;
  738.     } else if ( (long)htabof (i) < 0 )    /* empty slot */
  739.         goto nomatch;
  740.      disp = hsize_reg - i;        /* secondary hash (after G. Knott) */
  741.     if ( i == 0 )
  742.         disp = 1;
  743. probe:
  744.     if ( (i -= disp) < 0 )
  745.         i += hsize_reg;
  746.  
  747.     if ( htabof (i) == fcode ) {
  748.         ent = codetabof (i);
  749.         continue;
  750.     }
  751.     if ( (long)htabof (i) > 0 ) 
  752.         goto probe;
  753. nomatch:
  754.     output ( (code_int) ent );
  755.     out_count++;
  756.      ent = c;
  757. #ifdef SIGNED_COMPARE_SLOW
  758.     if ( (unsigned) free_ent < (unsigned) maxmaxcode) {
  759. #else
  760.     if ( free_ent < maxmaxcode ) {
  761. #endif
  762.          codetabof (i) = free_ent++;    /* code -> hashtable */
  763.         htabof (i) = fcode;
  764.     }
  765.     else if ( (count_int)in_count >= checkpoint && block_compress )
  766.         cl_block ();
  767.     }
  768.     /*
  769.      * Put out the final code.
  770.      */
  771.     output( (code_int)ent );
  772.     out_count++;
  773.     output( (code_int)-1 );
  774.  
  775.     /*
  776.      * Print out stats on stderr
  777.      */
  778.     if(zcat_flg == 0 && !quiet) {
  779. #ifdef DEBUG
  780.     fprintf( stderr,
  781.         "%ld chars in, %ld codes (%ld bytes) out, compression factor: ",
  782.         in_count, out_count, bytes_out );
  783.     prratio( stderr, in_count, bytes_out );
  784.     fprintf( stderr, "\n");
  785.     fprintf( stderr, "\tCompression as in compact: " );
  786.     prratio( stderr, in_count-bytes_out, in_count );
  787.     fprintf( stderr, "\n");
  788.     fprintf( stderr, "\tLargest code (of last block) was %d (%d bits)\n",
  789.         free_ent - 1, n_bits );
  790. #else /* !DEBUG */
  791.     fprintf( stderr, "Compression: " );
  792.     prratio( stderr, in_count-bytes_out, in_count );
  793. #endif /* DEBUG */
  794.     }
  795.     if(bytes_out > in_count)    /* exit(2) if no savings */
  796.     exit_stat = 2;
  797.     return;
  798. }
  799.  
  800. /*-
  801.  * Output the given code.
  802.  * Inputs:
  803.  *     code:    A n_bits-bit integer.  If == -1, then EOF.  This assumes
  804.  *        that n_bits =< (long)wordsize - 1.
  805.  * Outputs:
  806.  *     Outputs code to the file.
  807.  * Assumptions:
  808.  *    Chars are 8 bits long.
  809.  * Algorithm:
  810.  *     Maintain a BITS character long buffer (so that 8 codes will
  811.  * fit in it exactly).  Use the VAX insv instruction to insert each
  812.  * code in turn.  When the buffer fills up empty it and start over.
  813.  */
  814.  
  815. static char buf[BITS];
  816.  
  817. #ifndef vax
  818. char_type lmask[9] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
  819. char_type rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
  820. #endif /* vax */
  821.  
  822. void output( code )
  823. code_int  code;
  824. {
  825. #ifdef DEBUG
  826.     static int col = 0;
  827. #endif /* DEBUG */
  828.  
  829.     /*
  830.      * On the VAX, it is important to have the register declarations
  831.      * in exactly the order given, or the asm will break.
  832.      */
  833.     register int r_off = offset, bits= n_bits;
  834.     register char * bp = buf;
  835.  
  836. #ifdef DEBUG
  837.     if ( verbose )
  838.         fprintf( stderr, "%5d%c", code,
  839.             (col+=6) >= 74 ? (col = 0, '\n') : ' ' );
  840. #endif /* DEBUG */
  841.     if ( code >= 0 ) {
  842. #if defined(vax) && !defined(__GNUC__)
  843.     /*
  844.      * VAX and PCC DEPENDENT!! Implementation on other machines is
  845.      * below.
  846.      *
  847.      * Translation: Insert BITS bits from the argument starting at
  848.      * offset bits from the beginning of buf.
  849.      */
  850.     0;    /* Work around for pcc -O bug with asm and if stmt */
  851.     asm( "insv    4(ap),r11,r10,(r9)" );
  852. #else
  853. /* 
  854.  * byte/bit numbering on the VAX is simulated by the following code
  855.  */
  856.     /*
  857.      * Get to the first byte.
  858.      */
  859.     bp += (r_off >> 3);
  860.     r_off &= 7;
  861.     /*
  862.      * Since code is always >= 8 bits, only need to mask the first
  863.      * hunk on the left.
  864.      */
  865.     *bp = (*bp & rmask[r_off]) | (code << r_off) & lmask[r_off];
  866.     bp++;
  867.     bits -= (8 - r_off);
  868.     code >>= 8 - r_off;
  869.     /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
  870.     if ( bits >= 8 ) {
  871.         *bp++ = code;
  872.         code >>= 8;
  873.         bits -= 8;
  874.     }
  875.     /* Last bits. */
  876.     if(bits)
  877.         *bp = code;
  878. #endif /* vax */
  879.     offset += n_bits;
  880.     if ( offset == (n_bits << 3) ) {
  881.         bp = buf;
  882.         bits = n_bits;
  883.         bytes_out += bits;
  884.         do {
  885.         putchar(*bp++);
  886.         if (ferror(stdout))
  887.             writeerr();
  888.         } while(--bits);
  889.         offset = 0;
  890.     }
  891.  
  892.     /*
  893.      * If the next entry is going to be too big for the code size,
  894.      * then increase it, if possible.
  895.      */
  896.     if ( free_ent > maxcode || (clear_flg > 0))
  897.     {
  898.         /*
  899.          * Write the whole buffer, because the input side won't
  900.          * discover the size increase until after it has read it.
  901.          */
  902.         if ( offset > 0 ) {
  903.         if( fwrite( buf, 1, n_bits, stdout ) != n_bits)
  904.             writeerr();
  905.         bytes_out += n_bits;
  906.         }
  907.         offset = 0;
  908.  
  909.         if ( clear_flg ) {
  910.                 maxcode = MAXCODE (n_bits = INIT_BITS);
  911.             clear_flg = 0;
  912.         }
  913.         else {
  914.             n_bits++;
  915.             if ( n_bits == maxbits )
  916.             maxcode = maxmaxcode;
  917.             else
  918.             maxcode = MAXCODE(n_bits);
  919.         }
  920. #ifdef DEBUG
  921.         if ( debug ) {
  922.         fprintf( stderr, "\nChange to %d bits\n", n_bits );
  923.         col = 0;
  924.         }
  925. #endif /* DEBUG */
  926.     }
  927.     } else {
  928.     /*
  929.      * At EOF, write the rest of the buffer.
  930.      */
  931.     if ( offset > 0 ) {
  932.         offset = (offset + 7) / 8;
  933.         if( fwrite( buf, 1, offset, stdout ) != offset )
  934.             writeerr();
  935.         bytes_out += offset;
  936.     }
  937.     offset = 0;
  938.     (void)fflush( stdout );
  939.     if( ferror( stdout ) )
  940.         writeerr();
  941. #ifdef DEBUG
  942.     if ( verbose )
  943.         fprintf( stderr, "\n" );
  944. #endif
  945.     }
  946. }
  947.  
  948. /*
  949.  * Decompress stdin to stdout.  This routine adapts to the codes in the
  950.  * file building the "string" table on-the-fly; requiring no table to
  951.  * be stored in the compressed file.  The tables used herein are shared
  952.  * with those of the compress() routine.  See the definitions above.
  953.  */
  954.  
  955. void decompress(void) {
  956.     register char_type huge *stackp;
  957.     register int finchar;
  958.     register code_int code, oldcode, incode;
  959.     int    n, nwritten, offset;        /* Variables for buffered write */
  960.     char buff[BUFSIZ];            /* Buffer for buffered write */
  961.  
  962.  
  963.     /*
  964.      * As above, initialize the first 256 entries in the table.
  965.      */
  966.     maxcode = MAXCODE(n_bits = INIT_BITS);
  967.     for ( code = 255; code >= 0; code-- ) {
  968.     tab_prefixof(code) = 0;
  969.     tab_suffixof(code) = (char_type)code;
  970.     }
  971.     free_ent = ((block_compress) ? FIRST : 256 );
  972.  
  973.     finchar = oldcode = getcode();
  974.     if(oldcode == -1)    /* EOF already? */
  975.     return;            /* Get out of here */
  976.  
  977.     /* first code must be 8 bits = char */
  978.     n=0;
  979.     buff[n++] = (char)finchar;
  980.  
  981.     stackp = de_stack;
  982.  
  983.     while ( (code = getcode()) > -1 ) {
  984.  
  985.     if ( (code == CLEAR) && block_compress ) {
  986.         for ( code = 255; code >= 0; code-- )
  987.         tab_prefixof(code) = 0;
  988.         clear_flg = 1;
  989.         free_ent = FIRST - 1;
  990.         if ( (code = getcode ()) == -1 )    /* O, untimely death! */
  991.         break;
  992.     }
  993.     incode = code;
  994.     /*
  995.      * Special case for KwKwK string.
  996.      */
  997.     if ( code >= free_ent ) {
  998.             *stackp++ = finchar;
  999.         code = oldcode;
  1000.     }
  1001.  
  1002.     /*
  1003.      * Generate output characters in reverse order
  1004.      */
  1005. #ifdef SIGNED_COMPARE_SLOW
  1006.     while ( ((unsigned long)code) >= ((unsigned long)256) ) {
  1007. #else
  1008.     while ( code >= 256 ) {
  1009. #endif
  1010.         *stackp++ = tab_suffixof(code);
  1011.         code = tab_prefixof(code);
  1012.     }
  1013.     *stackp++ = finchar = tab_suffixof(code);
  1014.  
  1015.     /*
  1016.      * And put them out in forward order
  1017.      */
  1018.     do {
  1019.         /*
  1020.          * About 60% of the time is spent in the putchar() call
  1021.          * that appeared here.  It was originally
  1022.          *        putchar ( *--stackp );
  1023.          * If we buffer the writes ourselves, we can go faster (about
  1024.          * 30%).
  1025.          *
  1026.          * At this point, the next line is the next *big* time
  1027.          * sink in the code.  It takes up about 10% of the time.
  1028.          */
  1029.          buff[n++] = *--stackp;
  1030.          if (n == BUFSIZ) {
  1031.          offset = 0;
  1032.          do {
  1033.              nwritten = write(fileno(stdout), &buff[offset], n);
  1034.              if (nwritten < 0)
  1035.              writeerr();
  1036.              offset += nwritten;
  1037.          } while ((n -= nwritten) > 0);
  1038.           }
  1039.     } while ( stackp > de_stack );
  1040.  
  1041.     /*
  1042.      * Generate the new entry.
  1043.      */
  1044.     if ( (code=free_ent) < maxmaxcode ) {
  1045.         tab_prefixof(code) = (unsigned short)oldcode;
  1046.         tab_suffixof(code) = finchar;
  1047.         free_ent = code+1;
  1048.     } 
  1049.     /*
  1050.      * Remember previous code.
  1051.      */
  1052.     oldcode = incode;
  1053.     }
  1054.     /*
  1055.      * Flush the stuff remaining in our buffer...
  1056.      */
  1057.     offset = 0;
  1058.     while (n > 0) {
  1059.     nwritten = write(fileno(stdout), &buff[offset], n);
  1060.     if (nwritten < 0)
  1061.         writeerr();
  1062.     offset += nwritten;
  1063.     n -= nwritten;
  1064.     }
  1065. }
  1066.  
  1067. /*-
  1068.  * Read one code from the standard input.  If EOF, return -1.
  1069.  * Inputs:
  1070.  *     stdin
  1071.  * Outputs:
  1072.  *     code or -1 is returned.
  1073.  */
  1074. code_int
  1075. getcode(void) {
  1076.     /*
  1077.      * On the VAX, it is important to have the register declarations
  1078.      * in exactly the order given, or the asm will break.
  1079.      */
  1080.     register code_int code;
  1081.     static int offset = 0, size = 0;
  1082.     static char_type buf[BITS];
  1083.     register int r_off, bits;
  1084.     register char_type *bp = buf;
  1085.  
  1086.     if ( clear_flg > 0 || offset >= size || free_ent > maxcode ) {
  1087.     /*
  1088.      * If the next entry will be too big for the current code
  1089.      * size, then we must increase the size.  This implies reading
  1090.      * a new buffer full, too.
  1091.      */
  1092.     if ( free_ent > maxcode ) {
  1093.         n_bits++;
  1094.         if ( n_bits == maxbits )
  1095.         maxcode = maxmaxcode;    /* won't get any bigger now */
  1096.         else
  1097.         maxcode = MAXCODE(n_bits);
  1098.     }
  1099.     if ( clear_flg > 0) {
  1100.             maxcode = MAXCODE (n_bits = INIT_BITS);
  1101.         clear_flg = 0;
  1102.     }
  1103.     size = fread( buf, 1, n_bits, stdin );
  1104.     if ( size <= 0 )
  1105.     {
  1106.         return -1;            /* end of file */
  1107.     }
  1108.     offset = 0;
  1109.     /* Round size down to integral number of codes */
  1110.     size = (size << 3) - (n_bits - 1);
  1111.     }
  1112.     r_off = offset;
  1113.     bits = n_bits;
  1114. #ifdef vax
  1115.     asm( "extzv   r10,r9,(r8),r11" );
  1116. #else /* not a vax */
  1117.     /*
  1118.      * Get to the first byte.
  1119.      */
  1120.     bp += (r_off >> 3);
  1121.     r_off &= 7;
  1122.     /* Get first part (low order bits) */
  1123. #ifdef NO_UCHAR
  1124.     code = ((*bp++ >> r_off) & rmask[8 - r_off]) & 0xff;
  1125. #else
  1126.     code = (((long) *bp++) >> r_off);
  1127. #endif /* NO_UCHAR */
  1128.     bits -= (8 - r_off);
  1129.     r_off = 8 - r_off;        /* now, offset into code word */
  1130.     /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
  1131.     if ( bits >= 8 ) {
  1132. #ifdef NO_UCHAR
  1133.         code |= ((long) (*bp++ & 0xff)) << r_off;
  1134. #else
  1135.         code |= ((long) *bp++) << r_off;
  1136. #endif /* NO_UCHAR */
  1137.         r_off += 8;
  1138.         bits -= 8;
  1139.     }
  1140.     /* high order bits. */
  1141.     code |= ((long) (*bp & rmask[bits])) << r_off;
  1142. #endif /* vax */
  1143.     offset += n_bits;
  1144.  
  1145.     return code;
  1146. }
  1147.  
  1148. #ifdef DEBUG
  1149. printcodes()
  1150. {
  1151.     /*
  1152.      * Just print out codes from input file.  For debugging.
  1153.      */
  1154.     code_int code;
  1155.     int col = 0, bits;
  1156.  
  1157.     bits = n_bits = INIT_BITS;
  1158.     maxcode = MAXCODE(n_bits);
  1159.     free_ent = ((block_compress) ? FIRST : 256 );
  1160.     while ( ( code = getcode() ) >= 0 ) {
  1161.     if ( (code == CLEAR) && block_compress ) {
  1162.            free_ent = FIRST - 1;
  1163.            clear_flg = 1;
  1164.     }
  1165.     else if ( free_ent < maxmaxcode )
  1166.         free_ent++;
  1167.     if ( bits != n_bits ) {
  1168.         fprintf(stderr, "\nChange to %d bits\n", n_bits );
  1169.         bits = n_bits;
  1170.         col = 0;
  1171.     }
  1172.     fprintf(stderr, "%5d%c", code, (col+=6) >= 74 ? (col = 0, '\n') : ' ' );
  1173.     }
  1174.     putc( '\n', stderr );
  1175.     GlobalUnlock(hmemHtab);
  1176.     GlobalUnlock(hmemCodeTab);
  1177.     GlobalFree(hmemHtab);
  1178.     GlobalFree(hmemCodeTab);
  1179.     exit( 0 );
  1180. }
  1181.  
  1182. code_int sorttab[1<<BITS];    /* sorted pointers into htab */
  1183.  
  1184. dump_tab()    /* dump string table */
  1185. {
  1186.     register int i, first;
  1187.     register ent;
  1188. #define STACK_SIZE    15000
  1189.     int stack_top = STACK_SIZE;
  1190.     register c;
  1191.  
  1192.     if(do_decomp == 0) {    /* compressing */
  1193.     register int flag = 1;
  1194.  
  1195.     for(i=0; i<hsize; i++) {    /* build sort pointers */
  1196.         if((long)htabof(i) >= 0) {
  1197.             sorttab[codetabof(i)] = i;
  1198.         }
  1199.     }
  1200.     first = block_compress ? FIRST : 256;
  1201.     for(i = first; i < free_ent; i++) {
  1202.         fprintf(stderr, "%5d: \"", i);
  1203.         de_stack[--stack_top] = '\n';
  1204.         de_stack[--stack_top] = '"';
  1205.         stack_top = in_stack((htabof(sorttab[i])>>maxbits)&0xff, 
  1206.                                      stack_top);
  1207.         for(ent=htabof(sorttab[i]) & ((1<<maxbits)-1);
  1208.             ent > 256;
  1209.             ent=htabof(sorttab[ent]) & ((1<<maxbits)-1)) {
  1210.             stack_top = in_stack(htabof(sorttab[ent]) >> maxbits,
  1211.                         stack_top);
  1212.         }
  1213.         stack_top = in_stack(ent, stack_top);
  1214.         fwrite( &de_stack[stack_top], 1, STACK_SIZE-stack_top, stderr);
  1215.            stack_top = STACK_SIZE;
  1216.     }
  1217.    } else if(!debug) {    /* decompressing */
  1218.  
  1219.        for ( i = 0; i < free_ent; i++ ) {
  1220.        ent = i;
  1221.        c = tab_suffixof(ent);
  1222.        if ( isascii(c) && isprint(c) )
  1223.            fprintf( stderr, "%5d: %5d/'%c'  \"",
  1224.                ent, tab_prefixof(ent), c );
  1225.        else
  1226.            fprintf( stderr, "%5d: %5d/\\%03o \"",
  1227.                ent, tab_prefixof(ent), c );
  1228.        de_stack[--stack_top] = '\n';
  1229.        de_stack[--stack_top] = '"';
  1230.        for ( ; ent != NULL;
  1231.            ent = (ent >= FIRST ? tab_prefixof(ent) : NULL) ) {
  1232.            stack_top = in_stack(tab_suffixof(ent), stack_top);
  1233.        }
  1234.        fwrite( &de_stack[stack_top], 1, STACK_SIZE - stack_top, stderr );
  1235.        stack_top = STACK_SIZE;
  1236.        }
  1237.     }
  1238. }
  1239.  
  1240. int
  1241. in_stack(c, stack_top)
  1242.     register c, stack_top;
  1243. {
  1244.     if ( (isascii(c) && isprint(c) && c != '\\') || c == ' ' ) {
  1245.         de_stack[--stack_top] = c;
  1246.     } else {
  1247.         switch( c ) {
  1248.         case '\n': de_stack[--stack_top] = 'n'; break;
  1249.         case '\t': de_stack[--stack_top] = 't'; break;
  1250.         case '\b': de_stack[--stack_top] = 'b'; break;
  1251.         case '\f': de_stack[--stack_top] = 'f'; break;
  1252.         case '\r': de_stack[--stack_top] = 'r'; break;
  1253.         case '\\': de_stack[--stack_top] = '\\'; break;
  1254.         default:
  1255.          de_stack[--stack_top] = '0' + c % 8;
  1256.          de_stack[--stack_top] = '0' + (c / 8) % 8;
  1257.          de_stack[--stack_top] = '0' + c / 64;
  1258.          break;
  1259.         }
  1260.         de_stack[--stack_top] = '\\';
  1261.     }
  1262.     return stack_top;
  1263. }
  1264. #endif /* DEBUG */
  1265.  
  1266. void writeerr(void)
  1267. {
  1268.     (void)fprintf(stderr, "compress: writing to %s: %s\n",
  1269.         ofname[0] ? ofname : "stdout", strerror(errno));
  1270.     fprintf(stderr, "flags: %04x\n", stdout->flags);
  1271. /*    (void)unlink(ofname); */
  1272.     GlobalUnlock(hmemHtab);
  1273.     GlobalUnlock(hmemCodeTab);
  1274.     GlobalFree(hmemHtab);
  1275.     GlobalFree(hmemCodeTab);
  1276.     exit(1);
  1277. }
  1278.  
  1279. void copystat(ifname, ofname)
  1280. char *ifname, *ofname;
  1281. {
  1282.     struct stat statbuf;
  1283.     struct utimbuf tp;
  1284.  
  1285.     fclose(stdout);
  1286.     if (stat(ifname, &statbuf)) {        /* Get stat on input file */
  1287.     perror(ifname);
  1288.     return;
  1289.     }
  1290.     if ((statbuf.st_mode & S_IFMT/*0170000*/) != S_IFREG/*0100000*/) {
  1291.     if(quiet)
  1292.             fprintf(stderr, "%s: ", ifname);
  1293.     fprintf(stderr, " -- not a regular file: unchanged");
  1294.     exit_stat = 1;
  1295.     perm_stat = 1;
  1296.     } else if (statbuf.st_nlink > 1) {
  1297.     if(quiet)
  1298.             fprintf(stderr, "%s: ", ifname);
  1299.     fprintf(stderr, " -- has %d other links: unchanged",
  1300.         statbuf.st_nlink - 1);
  1301.     exit_stat = 1;
  1302.     perm_stat = 1;
  1303.     } else if (exit_stat == 2 && (!force)) { /* No compression: remove file.Z */
  1304.     if(!quiet)
  1305.         fprintf(stderr, " -- file unchanged");
  1306.     } else {            /* ***** Successful Compression ***** */
  1307.     exit_stat = 0;
  1308.     tp.actime = statbuf.st_atime;
  1309.     tp.modtime = statbuf.st_mtime;
  1310.     utime(ofname, &tp);    /* Update last accessed and modified times */
  1311.     if (unlink(ifname))    /* Remove input file */
  1312.         perror(ifname);
  1313.     if(!quiet)
  1314.         fprintf(stderr, " -- replaced with %s", ofname);
  1315.     return;        /* Successful return */
  1316.     }
  1317.  
  1318.     /* Unsuccessful return -- one of the tests failed */
  1319.     if (unlink(ofname))
  1320.     perror(ofname);
  1321. }
  1322.  
  1323. void
  1324. onintr ( )
  1325. {
  1326.     if (!precious)
  1327.     unlink ( ofname );
  1328.     exit ( 1 );
  1329. }
  1330.  
  1331. void
  1332. oops ( )    /* wild pointer -- assume bad input */
  1333. {
  1334.     if ( do_decomp ) 
  1335.         fprintf ( stderr, "uncompress: corrupt input\n" );
  1336.     unlink ( ofname );
  1337.     exit ( 1 );
  1338. }
  1339.  
  1340. void cl_block (void)        /* table clear for block compress */
  1341. {
  1342.     register long int rat;
  1343.  
  1344.     checkpoint = in_count + CHECK_GAP;
  1345. #ifdef DEBUG
  1346.     if ( debug ) {
  1347.             fprintf ( stderr, "count: %ld, ratio: ", in_count );
  1348.              prratio ( stderr, in_count, bytes_out );
  1349.         fprintf ( stderr, "\n");
  1350.     }
  1351. #endif /* DEBUG */
  1352.  
  1353.     if(in_count > 0x007fffff) {    /* shift will overflow */
  1354.     rat = bytes_out >> 8;
  1355.     if(rat == 0) {        /* Don't divide by zero */
  1356.         rat = 0x7fffffff;
  1357.     } else {
  1358.         rat = in_count / rat;
  1359.     }
  1360.     } else {
  1361.     rat = (in_count << 8) / bytes_out;    /* 8 fractional bits */
  1362.     }
  1363.     if ( rat > ratio ) {
  1364.     ratio = rat;
  1365.     } else {
  1366.     ratio = 0;
  1367. #ifdef DEBUG
  1368.     if(verbose)
  1369.         dump_tab();    /* dump string table */
  1370. #endif
  1371.      cl_hash ( (count_int) hsize );
  1372.     free_ent = FIRST;
  1373.     clear_flg = 1;
  1374.     output ( (code_int) CLEAR );
  1375. #ifdef DEBUG
  1376.     if(debug)
  1377.             fprintf ( stderr, "clear\n" );
  1378. #endif /* DEBUG */
  1379.     }
  1380. }
  1381.  
  1382. void cl_hash(hsize)        /* reset code table */
  1383.     register count_int hsize;
  1384. {
  1385.     register count_int huge *htab_p = htab+hsize;
  1386.     register long i;
  1387.     register long m1 = -1;
  1388.  
  1389.     i = hsize - 16;
  1390.      do {                /* might use Sys V memset(3) here */
  1391.         *(htab_p-16) = m1;
  1392.         *(htab_p-15) = m1;
  1393.         *(htab_p-14) = m1;
  1394.         *(htab_p-13) = m1;
  1395.         *(htab_p-12) = m1;
  1396.         *(htab_p-11) = m1;
  1397.         *(htab_p-10) = m1;
  1398.         *(htab_p-9) = m1;
  1399.         *(htab_p-8) = m1;
  1400.         *(htab_p-7) = m1;
  1401.         *(htab_p-6) = m1;
  1402.         *(htab_p-5) = m1;
  1403.         *(htab_p-4) = m1;
  1404.         *(htab_p-3) = m1;
  1405.         *(htab_p-2) = m1;
  1406.         *(htab_p-1) = m1;
  1407.         htab_p -= 16;
  1408.     } while ((i -= 16) >= 0);
  1409.         for ( i += 16; i > 0; i-- )
  1410.         *--htab_p = m1;
  1411. }
  1412.  
  1413. void prratio(stream, num, den)
  1414. FILE *stream;
  1415. long int num, den;
  1416. {
  1417.     register int q;            /* Doesn't need to be long */
  1418.  
  1419.     if(num > 214748L) {        /* 2147483647/10000 */
  1420.         q = num / (den / 10000L);
  1421.     } else {
  1422.         q = 10000L * num / den;        /* Long calculations, though */
  1423.     }
  1424.     if (q < 0) {
  1425.         putc('-', stream);
  1426.         q = -q;
  1427.     }
  1428.     fprintf(stream, "%d.%02d%%", q / 100, q % 100);
  1429. }
  1430.  
  1431. void usage(void)
  1432. {
  1433.     (void)fprintf(stderr,
  1434. #ifdef DEBUG
  1435.         "compress [-CDVcdfnv] [-b maxbits] [file ...]\n");
  1436. #else
  1437.         "compress [-Ccdfnv] [-b maxbits] [file ...]\n");
  1438. #endif
  1439.     GlobalUnlock(hmemHtab);
  1440.     GlobalUnlock(hmemCodeTab);
  1441.     GlobalFree(hmemHtab);
  1442.     GlobalFree(hmemCodeTab);
  1443.     exit(1);
  1444. }
  1445.